package com.jframe.sys.controller.listener;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import uk.ltd.getahead.dwr.WebContext;
import uk.ltd.getahead.dwr.WebContextFactory;

import com.jframe.sys.controller.utils.ActionMap;
import com.jframe.sys.controller.utils.BaseAction;
import com.jframe.sys.controller.utils.BaseDwr;
import com.jframe.sys.controller.utils.LogHandler;
import com.jframe.sys.controller.utils.SysConfig;
import com.jframe.sys.utils.FileUtil;
import com.jframe.sys.utils.StringUtil;
import com.jframe.sys.utils.Yz;


public class ActionListener implements Filter{

	static final long serialVersionUID = 1L;

	public String webRootRealPath = null;
	public ServletContext servletContext = null;
	protected FilterConfig filterConfig = null;
	public static String DEFAULT_METHODNAME = "service";
	protected Map methodCache = Collections.synchronizedMap(new HashMap());
	protected Class[] types1 = { HttpServletRequest.class,
			HttpServletResponse.class };
	protected Class[] types2 = {};
	private static Map classCache = null;
	private String actionBasePath;
	private String dispatchMethod;

	/**
	 * ForntController器初始化
	 */ 
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
		servletContext = filterConfig.getServletContext();
		webRootRealPath = servletContext.getRealPath("/");
		actionBasePath = filterConfig.getInitParameter("actionBasePath");
		if (actionBasePath == null) {
			actionBasePath = "action";
		}
		dispatchMethod = filterConfig.getInitParameter("dispatchMethod");
		if (dispatchMethod == null) {
			dispatchMethod = "doMethod";
		}
		//if(Yz.yz()){
			servletContext.setAttribute("license", "true");
		//}else{
		//	servletContext.setAttribute("license", "false");
		//}
	}

	protected BaseAction loadAction(HttpServletRequest request,
			HttpServletResponse response) {

		String servletPath = request.getRequestURI();
		String actionName = servletPath;
		try {
			int si = servletPath.lastIndexOf("/");
			int di = servletPath.lastIndexOf(".");
			servletPath = servletPath.substring(si + 1, di);
			if(classCache==null){
				classCache=ActionMap.getClassCache();
			}
			Class klazz = (Class) classCache.get(servletPath);
			BaseAction action = (BaseAction) klazz.newInstance();
			action.init(request, response);
			return action;
		} catch (Exception e) {
			e.printStackTrace();
			LogHandler.error(actionName + "指定的Action不存在，请检查配置文件中是否已包含指定的");
			return null;
		}
	}

	private String getMethodName(HttpServletRequest request) {
		return request.getParameter(dispatchMethod);
	}

	protected Method getMethod(Class clazz, String name, Class[] pTypes) {
		try {
			return clazz.getMethod(name, pTypes);
		} catch (NoSuchMethodException e) {
			return null;
		}
	}

	protected Method getMethod(Class clazz, String name) {
		String key = clazz.getName() + "/" + name;
		Method method = (Method) methodCache.get(key);
		if (method == null) {
			Exception mE = null;
			try {
				method = clazz.getMethod(name, types1);
			} catch (Exception e1) {
				mE = e1;
				try {
					method = clazz.getMethod(name, types2);
				} catch (Exception e2) {
					mE = e2;
					method = null;
				}
			}
			if (method == null) {
				LogHandler.warn(this,
						new NoSuchMethodException(mE.getMessage()));
			} else {
				methodCache.put(key, method);
			}
		}
		return method;
	}

	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		request.setCharacterEncoding(SysConfig.getEncoding());
		response.setContentType(SysConfig.getEncoding());
		response.setCharacterEncoding(SysConfig.getEncoding());
		BaseAction action = loadAction(request, response);
		String name = getMethodName(request);
		String license = (String)request.getSession().getServletContext().getAttribute("license");
		if (action == null) {
			response.sendError(404);
			response.setContentType("text/html; charset="+SysConfig.getEncoding());
			PrintWriter out = response.getWriter();
			out.println("<html><body>Action not found!</body></html>");
			out.flush();
			out.close();
		} else if(license.equals("false")){
			response.sendError(800);
			response.setContentType("text/html; charset="+SysConfig.getEncoding());
			PrintWriter out = response.getWriter();
			out.println("<html><body>授权文件已过期或者验证出错。请联系l2iu工作，提供主机mac地址申请新授权，联系邮件为：l2iu11@163.com。</body></html>");
			out.flush();
			out.close();
		}else {
			String actionPath = request.getRequestURI();
			int si = actionPath.lastIndexOf("/");
			int di = actionPath.lastIndexOf(".");
			actionPath = actionPath.substring(si + 1, di);
			boolean isLogin = ActionMap.hasWebRight(actionPath,
					name); //
			if (isLogin || action.getCurUser() != null) {
				isLogin = true;
			}
			if (isLogin) {
				Object[] args = { request, response };
				Method method = getMethod(action.getClass(), name);
				try {
					if (method.getParameterTypes().length == 0) {
						method.invoke(action, (Object[]) null);
					} else {
						method.invoke(action, args);
					}
				} catch (Exception e) {
					LogHandler.warn(e);
					throw new ServletException(e);
				} finally {
					action.dispose();
				}
				return;
			} else {
				response.sendError(401);
				response.setContentType("text/html; charset="+SysConfig.getEncoding());
				PrintWriter out = response.getWriter();
				out.println("<html><body>没有授权!</body></html>");
				out.flush();
				out.close();
			}
		}
	}

	protected String getWebRootRealPath() {
		return webRootRealPath;
	}

	public void destroy() {
		webRootRealPath = null;
		servletContext = null;
		filterConfig = null;
		methodCache = null;
		types1 = null;
		types2 = null;
		classCache = null;
		actionBasePath = null;
		//viewBasePath = null;
		dispatchMethod = null;
	}

	// 使用json字符串作为参数
	public String dwrService4Json(String actionName, String methodName,
			String args) throws IOException, ServletException {
		Object[] aryObj = { args };
		return this.dwrInvoke(actionName, methodName, aryObj);
	}

	// 使用数组作为参数
	public String dwrService(String actionName, String methodName,
			String args[]) throws IOException, ServletException {
		Object[] aryObj = { args };
		return this.dwrInvoke(actionName, methodName, aryObj);
	}

	private String dwrInvoke(String actionName, String methodName,
			Object[] aryObj) throws IOException, ServletException {
		BaseDwr dwr = new BaseDwr();
		HttpServletResponse response = dwr.getResponce();
		HttpServletRequest request = dwr.getRequest();
		// 装载action
		if(classCache==null){
			classCache=ActionMap.getClassCache();
		}
		Class klazz = (Class) classCache.get(actionName);
		BaseAction action = null;
		boolean isLogin = ActionMap.hasWebRight(actionName, methodName); //
		try {
			action = (BaseAction) klazz.newInstance();
			action.init(request, response);
			if (isLogin || action.getCurUser() != null) {
				isLogin = true;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (action == null) {
			response.sendError(404);
			response.setContentType("text/html; charset="+SysConfig.getEncoding());
			return "<html><body>Action not found!</body></html>";
		} else if (isLogin) {
			String returnValue = null;
			Class[] aryClass = new Class[1];
			aryClass[0] = String[].class;
			try {
				Method method = action.getClass().getMethod(methodName,
						aryClass);
				returnValue = (String) method.invoke(action, aryObj);
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return returnValue;

		} else {
			return "401";
		}
	}
	

	public static String threadTask(String actionName, String methodName,
			Object args[]) {		
		String returnValue = null;
		try {
			if(classCache==null){
				classCache=ActionMap.getClassCache();
			}
			Class klazz = (Class) classCache.get(actionName);
			BaseAction action = (BaseAction) klazz.newInstance();
			if (action == null) {
				LogHandler.warn("任务配置的Action不存在！");
				return "false";
			}
			Class[] aryClass = new Class[] { Object[].class };
			Method method = action.getClass().getMethod(methodName, aryClass);
			returnValue = (String) method.invoke(action, new Object[] { args });

		} catch (Exception e) {
			e.printStackTrace();
		}
		return returnValue;
	}
	
    /**
     * 检测文件大小
     * @param uploadFile
     * @return
     */
	public String getFileSize(InputStream uploadFile){
		try{
			int available = uploadFile.available() /1024;
			return available+"";
		}
		catch(Exception ex){
			return "0";
		}
	}
	
	
	public String uploadFile(InputStream uploadFile, String filename) {
		try {
			WebContext webContext = WebContextFactory.get();
			String realtivepath = "/upload/";
			String saveurl = webContext.getHttpServletRequest().getSession()
					.getServletContext().getRealPath("/upload");
			File file = new File(saveurl + "/" + filename);
			FileUtil.mkDir(saveurl); // 如果目录不存在则建立新目录
			int available = uploadFile.available();
			FileOutputStream foutput = new FileOutputStream(file);
			int off = 0;
			int m10 = 1024 * 1024 * 10;
			int len = available > m10 ? m10 : available;

			byte[] b = new byte[len];
			while (uploadFile.read(b, 0, len) != -1) {
				foutput.write(b, 0, len);
				// off +=len;
				// b = new byte[len];
				int l = uploadFile.available();
				if (l < len && l > 0) {
					len = l;
				}
				System.out.println(l);
			}
			foutput.flush();
			foutput.close();
			uploadFile.close();
			return realtivepath + filename;
		} catch (Exception ex) {

			ex.printStackTrace();
			return "";
		}
	}
   

	public String uploadFile2Dir(InputStream uploadFile, String dir,
			String filename) {
		try {
			dir = StringUtil.trimAll(dir);
			WebContext webContext = WebContextFactory.get();
			String realtivepath = "/upload/" + dir + "/";
			String saveurl = webContext.getHttpServletRequest().getSession()
					.getServletContext().getRealPath("/upload")
					+ File.separator + dir;
			filename = System.currentTimeMillis()
					+ filename.substring(filename.lastIndexOf("."));
			File file = new File(saveurl + "/" + filename);
			FileUtil.mkDirs(saveurl); // 如果目录不存在则建立新目录
			int available = uploadFile.available();
			FileOutputStream foutput = new FileOutputStream(file);
			int off = 0;
			int m10 = 1024 * 1024 * 10;
			int len = available > m10 ? m10 : available;

			byte[] b = new byte[len];
			while (uploadFile.read(b, 0, len) != -1) {
				foutput.write(b, 0, len);
				int l = uploadFile.available();
				if (l < len && l > 0) {
					len = l;
				}
				//System.out.println(l);
			}
			foutput.flush();
			foutput.close();
			uploadFile.close();
			return realtivepath + filename;
		} catch (Exception ex) {

			ex.printStackTrace();
			return "";
		}
	}
	
	public String uploadFile(InputStream uploadFile, String dir,
			String filename,int maxSize) {
		try {
			dir = StringUtil.trimAll(dir);
			WebContext webContext = WebContextFactory.get();
			String realtivepath = "/upload/" + dir + "/";
			String saveurl = webContext.getHttpServletRequest().getSession()
					.getServletContext().getRealPath("/upload")
					+ File.separator + dir;
			filename = System.currentTimeMillis()
					+ filename.substring(filename.lastIndexOf("."));
			File file = new File(saveurl + "/" + filename);
			FileUtil.mkDirs(saveurl); // 如果目录不存在则建立新目录
			int available = uploadFile.available();
			
			if(available/1024 > maxSize) return "{\"isSuccess\":\"false\",\"msg\":\"您上传的文件超过"+maxSize+"kb\"}";//
			FileOutputStream foutput = new FileOutputStream(file);
			int off = 0;
			int m10 = 1024 * 1024 * 10;
			int len = available > m10 ? m10 : available;

			byte[] b = new byte[len];
			while (uploadFile.read(b, 0, len) != -1) {
				foutput.write(b, 0, len);
				int l = uploadFile.available();
				if (l < len && l > 0) {
					len = l;
				}
				//System.out.println(l);
			}
			foutput.flush();
			foutput.close();
			uploadFile.close();
			return "{\"isSuccess\":\"true\",\"msg\":\""+realtivepath + filename+"\"}";
		} catch (Exception ex) {
			ex.printStackTrace();
			return "{\"isSuccess\":\"false\",\"msg\":\"文件上传异常请重试\"}";
		}
	}
 

}
